package com.byxy.muxinnetty.service.impl;

import com.byxy.muxinnetty.enums.MsgActionEnum;
import com.byxy.muxinnetty.enums.MsgSignFlagEnum;
import com.byxy.muxinnetty.enums.SearchFriendsStatusEnum;
import com.byxy.muxinnetty.mapper.*;
import com.byxy.muxinnetty.netty.ChatMsg;
import com.byxy.muxinnetty.netty.DataContent;
import com.byxy.muxinnetty.netty.UserChannelRel;
import com.byxy.muxinnetty.pojo.FriendsRequest;
import com.byxy.muxinnetty.pojo.MyFriends;
import com.byxy.muxinnetty.pojo.Users;
import com.byxy.muxinnetty.service.UserService;
import com.byxy.muxinnetty.utils.FastDFSClient;
import com.byxy.muxinnetty.utils.FileUtils;
import com.byxy.muxinnetty.utils.JsonUtils;
import com.byxy.muxinnetty.utils.QRCodeUtils;
import com.byxy.muxinnetty.vo.FriendRequestVO;
import com.byxy.muxinnetty.vo.MyFriendsVO;
import com.google.zxing.WriterException;
import io.netty.channel.Channel;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import org.n3r.idworker.Sid;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.List;

@Service
@Transactional
public class UserServiceImpl implements UserService {

    @Resource
    private UsersMapper usersMapper;
    @Resource
    private UsersMapperCustom usersMapperCustom;
    @Resource
    private MyFriendsMapper myFriendsMapper;
    @Resource
    private FriendsRequestMapper friendsRequestMapper;
    @Resource
    private Sid sid;
    @Resource
    private QRCodeUtils qrCodeUtils;
    @Resource
    private FastDFSClient fastDFSClient;
    @Resource
    private ChatMsgMapper chatMsgMapper;

    public final static String IMG_PATH_PREFIX = "static/qrcode";

    @Override
    public boolean queryUsernameIsExist(String username) {
        Users users = new Users();
        users.setUsername(username);

        Users result = usersMapper.selectOne(users);

        return result != null ? true : false;
    }

    @Override
    public Users queryUserForLogin(String username, String password) {

        Example userExample = new Example(Users.class);
        Example.Criteria criteria = userExample.createCriteria();

        criteria.andEqualTo("username", username);
        criteria.andEqualTo("password", password);

        Users result = usersMapper.selectOneByExample(userExample);

        return result;
    }

    @Override
    public Users saveUser(Users users) throws IOException, WriterException {

        String userId = sid.nextShort();

        // 为每个用户生成一个唯一的二维码
        String fileDirPath = new String("src/main/resources/" + IMG_PATH_PREFIX);
        File fileDir = new File(fileDirPath);
        if (!fileDir.exists()) {
            // 递归生成文件夹
            fileDir.mkdirs();
        }
        String qrCodePath = fileDirPath + File.separator + userId + "qrcode.png";
        // muxin_qrcode:[username]
        qrCodeUtils.createQRCode(qrCodePath, "muxin_qrcode:" + users.getUsername());
        MultipartFile qrCodeFile = FileUtils.fileToMultipart(qrCodePath);

        String qrCodeUrl = "";

        qrCodeUrl = fastDFSClient.uploadQRCode(qrCodeFile);

        users.setQrcode(qrCodeUrl);

        users.setId(userId);
        usersMapper.insert(users);

        return users;
    }

    @Override
    public Users uppdateUserInfo(Users users) {
        usersMapper.updateByPrimaryKeySelective(users);
        return usersMapper.selectByPrimaryKey(users);
    }

    @Override
    public Integer preconditionSearchFriends(String myUserId, String friendUsername) {
        Users users = queryUserInfoByUsername(friendUsername);
        // 1.搜索的用户如果不存在，返回[没有此用户]
        if (users == null) {
            return SearchFriendsStatusEnum.USER_NOT_EXIST.status;
        }
        // 2.搜索账号是你自己，返回[不能添加你自己]
        if (users.getId().equals(myUserId)) {
            return SearchFriendsStatusEnum.NOT_YOURSELF.status;
        }
        // 3.搜索的朋友已经是你的好友，返回[该用户已经是你的好友]
        Example myFriends = new Example(MyFriends.class);
        Example.Criteria criteria = myFriends.createCriteria();
        criteria.andEqualTo("myUserId", myUserId);
        criteria.andEqualTo("myFriendUserId", users.getId());
        MyFriends mf = myFriendsMapper.selectOneByExample(myFriends);
        if (mf != null) {
            return SearchFriendsStatusEnum.ALREADY_FRIENDS.status;
        }
        return SearchFriendsStatusEnum.SUCCESS.status;
    }

    @Override
    public Users queryUserInfoByUsername(String username) {
        Example user = new Example(Users.class);
        Example.Criteria criteria = user.createCriteria();
        criteria.andEqualTo("username", username);
        return usersMapper.selectOneByExample(user);
    }

    @Override
    public void sendFriendRequest(String myUserId, String friendUsername) {

        // 根据用户名把朋友信息查询出来
        Users friend = queryUserInfoByUsername(friendUsername);

        // 1. 查询发送好友请求记录表
        Example example = new Example(FriendsRequest.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("sendUserId", myUserId);
        criteria.andEqualTo("acceptUserId", friend.getId());
        FriendsRequest friendRequest = friendsRequestMapper.selectOneByExample(example);
        if (friendRequest == null) {
            // 2. 如果不是你的好友，并且好友记录没有添加，则新增好友请求记录
            String requestId = sid.nextShort();

            FriendsRequest request = new FriendsRequest();
            request.setId(requestId);
            request.setSendUserId(myUserId);
            request.setAcceptUserId(friend.getId());
            request.setRequestDateTime(new Date());
            friendsRequestMapper.insert(request);
        }
    }

    @Override
    public List<FriendRequestVO> queryFriendRequestList(String acceptUserId) {
        return usersMapperCustom.queryFriendRequestList(acceptUserId);
    }

    @Override
    public void deleteFriendRequest(String acceptUserId, String sendUserId) {
        Example example = new Example(FriendsRequest.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("sendUserId", sendUserId);
        criteria.andEqualTo("acceptUserId", acceptUserId);
        FriendsRequest friendsRequest = friendsRequestMapper.selectOneByExample(example);
        friendsRequestMapper.delete(friendsRequest);
    }

    @Override
    public void passFriendRequest(String acceptUserId, String sendUserId) {
        saveFriend(acceptUserId, sendUserId);
        saveFriend(sendUserId, acceptUserId);
        deleteFriendRequest(acceptUserId, sendUserId);

        Channel channel = UserChannelRel.get(sendUserId);
        if (channel != null){
            // 使用websocket主动推送消息到请求发起者,更新的通讯录列表为最新
            DataContent dataContent = new DataContent();
            dataContent.setAction(MsgActionEnum.PULL_FRIEND.type);

            channel.writeAndFlush(new TextWebSocketFrame(JsonUtils.objectToJson(dataContent)));
        }
    }

    @Override
    public List<MyFriendsVO> queryMyFriends(String userId) {
        List<MyFriendsVO> myFriends = usersMapperCustom.queryMyFriends(userId);
        return myFriends;
    }

    @Override
    public String saveMsg(ChatMsg chatMsg) {
        com.byxy.muxinnetty.pojo.ChatMsg msgDB = new com.byxy.muxinnetty.pojo.ChatMsg();
        String msgId = sid.nextShort();
        msgDB.setId(msgId);
        msgDB.setAcceptUserId(chatMsg.getReceiverId());
        msgDB.setSendUserId(chatMsg.getSenderId());
        msgDB.setCreateTime(new Date());
        msgDB.setSignFlag(MsgSignFlagEnum.UNSIGN.type);
        msgDB.setMsg(chatMsg.getMsg());

        chatMsgMapper.insert(msgDB);
        return msgId;
    }

    @Override
    public void updateMsgSigned(List<String> msgIdList) {
        usersMapperCustom.batchUpdateMsgSigned(msgIdList);
    }

    @Override
    public List<com.byxy.muxinnetty.pojo.ChatMsg> getUnReadMsgList(String acceptUserId) {
        Example example = new Example(com.byxy.muxinnetty.pojo.ChatMsg.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("signFlag",0);
        criteria.andEqualTo("acceptUserId",acceptUserId);

        List<com.byxy.muxinnetty.pojo.ChatMsg> result = chatMsgMapper.selectByExample(example);

        return result;
    }

    private void saveFriend(String acceptUserId, String sendUserId) {
        MyFriends myFriends = new MyFriends();
        String recordId = sid.nextShort();
        myFriends.setId(recordId);
        myFriends.setMyFriendUserId(sendUserId);
        myFriends.setMyUserId(acceptUserId);
        myFriendsMapper.insert(myFriends);
    }
}
